package town;

import etc.Mule;
import game.Game;
import game.GameDriver;
import game.ResourceBasket;
import game.Round;
import game.Transaction;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

/**
 * Store is building in Town through which players can purchase goods.
 * 
 * @author Bradley, Yasasvi
 */
public class Store extends TownBuilding implements Transaction {

    /** Auto-generated serial version ID. */
    private static final long serialVersionUID = -7065925416623615386L;

    private ResourceBasket basket;
    private Game currentGame;
    private JPanel store;

    JLabel[] resourceLabels;
    String[] resourceTitles;
    JLabel food;
    JLabel energy;
    JLabel smithore;
    JLabel crystite;
    JLabel mule;

    JTextField foodField;
    JTextField energyField;
    JTextField smithoreField;
    JTextField crystiteField;

    JComboBox muleOptions;

    JButton buy;
    JButton sell;

    public Store(Game currentGame, GameDriver driver, Round round) {
	super(currentGame, driver, round);
	this.currentGame = currentGame;
	this.driver = driver;

	setInitialResources();

	remove(super.getBuildingPanel());
	store = new JPanel();
	add(store, BorderLayout.CENTER);
	store.setLayout(new GridLayout(5, 4));

	resourceLabels = new JLabel[6];
	resourceTitles = new String[6];

	// adds titles to array
	resourceTitles[0] = "Food Left: ";
	resourceTitles[1] = "Energy Left: ";
	resourceTitles[2] = "Smithore Left: ";
	resourceTitles[3] = "Crystite Left: ";
	resourceTitles[5] = "Mules Left: ";

	// adds resources to labels
	resourceLabels[0] = food = new JLabel("Food Left: " + basket.getResource(0),
		JLabel.CENTER);
	resourceLabels[1] = energy = new JLabel("Energy Left: "
		+ basket.getResource(1), JLabel.CENTER);
	resourceLabels[2] = smithore = new JLabel("Smithore Left: "
		+ basket.getResource(2), JLabel.CENTER);
	resourceLabels[3] = crystite = new JLabel("Crystite Left: "
		+ basket.getResource(4), JLabel.CENTER);
	resourceLabels[5] = mule = new JLabel("Mules Left: " + basket.getResource(5),
		JLabel.CENTER);
	
	//initializes the text fields for setting quantities to buy/sell
	foodField = new JTextField("1", JTextField.CENTER);
	foodField.setToolTipText("How much food to buy/sell?");
	energyField = new JTextField("1", JTextField.CENTER);
	energyField.setToolTipText("How much energy to buy/sell?");
	smithoreField = new JTextField("1", JTextField.CENTER);
	smithoreField.setToolTipText("How much smithore to buy/sell?");
	crystiteField = new JTextField("1", JTextField.CENTER);
	crystiteField.setToolTipText("How much crystite to buy/sell?");

	muleOptions = new JComboBox(new String[] { "Food Mule", "Energy Mule",
		"Smithore Mule", "Crystite Mule" });
	muleOptions.setToolTipText("What type of mule do you want?");

	// adds each buy sell button to each resource
	addResourceButton(food, foodField, 0);
	addResourceButton(energy, energyField, 1);
	addResourceButton(smithore, smithoreField, 2);
	addResourceButton(crystite, crystiteField, 3);
	addMuleButton(mule, muleOptions, 5);

    }

    private void addResourceButton(JLabel label, JTextField field, int i) {
	store.add(label);
	store.add(field);
	addButtons(i);
    }

    private void addMuleButton(JLabel label, JComboBox box, int i) {
	store.add(label);
	store.add(box);
	addButtons(i);
    }

    private void addButtons(int i) {
	buy = new JButton("Buy");
	buy.addActionListener(new BuyListener(i));
	buy.setBorder(null);
	buy.setIcon(new ImageIcon(this.getClass().getResource("/images/buy.png")));
	buy.setBorder(null);
	store.add(buy);
	sell = new JButton("Sell");
	sell.addActionListener(new SellListener(i));
	sell.setBorder(null);
	sell.setIcon(new ImageIcon(this.getClass().getResource("/images/sell.png")));
	sell.setBorder(null);
	store.add(sell);
    }

    /**
     * Sets the initial resources of the store through Game.
     */
    public void setInitialResources() {
	this.basket = currentGame.getInitialStoreResources();
    }

    public ResourceBasket getResourceBasket() {
	return basket;
    }

    /**
     * Buying resource from store.
     * 
     * @param resourceType Type of resource
     * @param count Amount buying
     * @param pricePerUnit Price per unit being bought
     */
    public boolean sellResource(int resourceType, int count,
	    int pricePerUnit) {
	// resource basket of the current player
	ResourceBasket currentBasket = round.getCurrPlayerResourceBasket();
	int totalCost = count * pricePerUnit;

	if (basket.getResource(resourceType) >= count
		&& (totalCost < round.getCurrPlayer().getResourceBasket()
			.getResource(4))) {

	    if (resourceType != 5) { // if not buying a mule
		// subtract from the store
		basket.subtractResource(resourceType, count);
		// add to player's basket
		currentBasket.addResource(resourceType, count);
		// subtract player's money
		currentBasket.subtractResource(4, totalCost);
		resourceLabels[resourceType]
			.setText(resourceTitles[resourceType]
				+ basket.getResource(resourceType));
		return true;
	    } else if (!round.getCurrPlayer().hasMule()) {
		// if you don't have a mule and you try to buy one
		basket.subtractResource(resourceType, 1);
		round.getCurrPlayer().buyMule(muleOptions.getSelectedIndex());
		resourceLabels[resourceType]
			.setText(resourceTitles[resourceType]
				+ basket.getResource(resourceType));
		driver.toPanel(round.getMapPanel(), BorderLayout.CENTER);
		
		//Sets custom cursor
		Toolkit toolkit = Toolkit.getDefaultToolkit();
		ImageIcon icon = new ImageIcon(this.getClass().getResource("/images/mule-"+muleOptions.getSelectedIndex()+".png"));
		Image image = icon.getImage();
		Cursor c = toolkit.createCustomCursor(image, new Point(0,0), "mule-"+muleOptions.getSelectedIndex());
		round.getMapPanel().setCursor(c);
		
		return true;
	    } else {
		Component frame = null;
		JOptionPane.showMessageDialog(frame,
			"You can only have one mule at a time");
	    }
	} else if (basket.getResource(resourceType) < count) {
	    // not enough stock
	    Component frame = null;
	    JOptionPane.showMessageDialog(frame,
		    "The Store does not have enough of this item. "
			    + "Please try again with a lower amount");
	} else if ((totalCost > round.getCurrPlayer().getResourceBasket()
		.getResource(4))) { // not enough money
	    Component frame = null;
	    JOptionPane.showMessageDialog(frame,
		    "You don't have enough money to buy this item");
	}
	return false;
    }

    /**
     * Selling resource to store.
     * 
     * @param resourceType Type of resource
     * @param count Amount selling
     * @param pricePerUnit Price per unit being sold
     */
    public boolean buyResource(int resourceType, int count,
	    int pricePerUnit) {

	int totalCost = count * pricePerUnit;
	ResourceBasket currentBasket = round.getCurrPlayerResourceBasket();

	if (resourceType != 5
		&& currentBasket.getResource(resourceType) >= count) {
	    // add to the store
	    basket.addResource(resourceType, count);
	    // subtract from player's basket
	    currentBasket.subtractResource(resourceType, count);
	    // add player's money
	    currentBasket.addResource(4, totalCost);
	    resourceLabels[resourceType].setText(resourceTitles[resourceType]
		    + basket.getResource(resourceType));
	    round.updateInfoPanel();
	    return true;
	}

	if (resourceType == 5 && round.getCurrPlayer().hasMule()) {
	    round.getCurrPlayer().removeMule();
	    basket.addResource(resourceType, count);
	    resourceLabels[resourceType].setText(resourceTitles[resourceType]
		    + basket.getResource(resourceType));
	    round.updateInfoPanel();
	}

	else if (currentBasket.getResource(resourceType) < count) {
	    Component frame = null;
	    JOptionPane.showMessageDialog(frame,
		    "You can't sell more than you have!");
	}
	return false;
    }

    /**
     * Action listener for Buy button.
     * 
     * @author Yasasvi
     */
    class BuyListener implements ActionListener {
	int resource;

	public BuyListener(int resource) {
	    this.resource = resource;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
	    if (resource == 0) 
		sellResource(resource,
			Integer.parseInt(foodField.getText()), 30);
	    else if (resource == 1)
		sellResource(resource,
			Integer.parseInt(energyField.getText()), 25);
	    else if (resource == 2)
		sellResource(resource,
			Integer.parseInt(smithoreField.getText()), 50);
	    else if (resource == 3)
		sellResource(resource,
			Integer.parseInt(crystiteField.getText()), 100);
	    else if (resource == 5)
		sellResource(resource, 1, 25);
	    // updates InfoPanel with current resources
	    round.updateInfoPanel();
	}

    }

    /**
     * Action listener for Sell button.
     * 
     * @author Yasasvi
     */
    class SellListener implements ActionListener {
	int resource;

	public SellListener(int resource) {
	    this.resource = resource;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
	    if (resource == 0)
		buyResource(resource,
			Integer.parseInt(foodField.getText()), 30);
	    else if (resource == 1)
		buyResource(resource,
			Integer.parseInt(energyField.getText()), 25);
	    else if (resource == 2)
		buyResource(resource,
			Integer.parseInt(smithoreField.getText()), 50);
	    else if (resource == 3)
		buyResource(resource,
			Integer.parseInt(crystiteField.getText()), 100);
	    else if (resource == 5)
		buyResource(resource, 1, 25);
	    // updates InfoPanel with current resources
	    round.updateInfoPanel();
	}
    }
}